home *** CD-ROM | disk | FTP | other *** search
Wrap
// DO NOT import this into the global namespace, but instead // import it into your own namespace wrapper var EXPORTED_SYMBOLS = ["Utils"]; Components.utils.import("resource://glydo/utils/prototype_xul_1_6_0_3_modified.jsm"); var window = Components.classes["@mozilla.org/appshell/appShellService;1"] .getService(Components.interfaces.nsIAppShellService) .hiddenDOMWindow; var document = window.document; var Utils = { unescapeHTMLIfNecessary: function(s) { try { return Prototype.S.unescapeHTML(s); } catch (ignore) { return s; } }, setTimeout: function(func, delay) { var timer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer); var callback = { that: this, notify: function () { func.call(this.that); } }; timer.initWithCallback(callback, delay, Components.interfaces.nsITimer.TYPE_ONE_SHOT); return timer; }, clearTimeout: function(timer) { timer.cancel(); }, setInterval: function(func, delay) { var timer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer); var callback = { that: this, notify: function () { func.call(this.that); } }; timer.initWithCallback(callback, delay, Components.interfaces.nsITimer.TYPE_REPEATING_PRECISE); return timer; }, clearInterval: function(timer) { timer.cancel(); }, arrayify: function(obj) { if (obj === null || obj === undefined) { return []; } if (Prototype.O.isArray(obj)) { return obj; } return [obj]; }, compareVersionNumbers: function(v1,v2) { var v1parts = v1.split("."); var v2parts = v2.split("."); var l = Math.max(v1parts.length,v2parts.length); for (var i = 0; i < l; ++i) { var p1 = v1parts[i] || '0'; var p2 = v2parts[i] || '0'; if (p1 !== p2) { var parts1 = /^([0-9]*)([^0-9]*)([0-9]*)([^0-9]*)$/.exec(p1); if (parts1 === null) { throw "Not a valid version number: " + v1; } var parts2 = /^([0-9]*)([^0-9]*)([0-9]*)([^0-9]*)$/.exec(p2); if (parts2 === null) { throw "Not a valid version number: " + v2; } for (var j = 1; j <= 4; ++j) { var c = this.compareVersionNumberPartPart(parts1[j],parts2[j],!(j & 1)); if (c > 0) { return 1; } if (c < 0) { return -1; } } } } return 0; }, compareVersionNumberPartPart: function(p1,p2,stringcomp) { if (!stringcomp) { // Numeric part comparison p1 = parseInt(p1); p2 = parseInt(p2); } else { // String part comparison if (p1 === p2) { return 0; } // If a string part is missing, it is greater than the other if (!p1 && p2) { return -1; } if (!p2 && p1) { return 1; } } // Compare the two parts (as numbers of bytes, depending on // the previous manipulations if (p1 < p2) { return 1; } if (p1 > p2) { return -1; } return 0 }, uuid1: function() { var uuidGenerator = Components.classes["@mozilla.org/uuid-generator;1"] .getService(Components.interfaces.nsIUUIDGenerator); var uuid = uuidGenerator.generateUUID(); return uuid.toString().slice(1,-1); }, shuffle: function(values) { var l = values.length; for (var i = 0; i < l-1; ++i) { var j = Math.floor(Math.random()*(l-i))+i; var t = values[i]; values[i] = values[j]; values[j] = t; } }, promptService: function() { var service = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]; return service.getService(Components.interfaces.nsIPromptService); }, platformLong: function() { return window.navigator.platform.toLowerCase(); }, platformShort: function() { var platform = this.platformLong(); if (platform.indexOf('linux') != -1) { return 'linux'; } if (platform.indexOf('mac') != -1) { return 'mac'; } if (platform.indexOf('win') != -1) { return 'windows'; } return 'unknown'; }, containerAppVersion: function() { var ver = null; try { ver = APP_INFO.version; } catch (e) { } return ver; }, appName: function() { var name = "unknown"; try { var id = APP_INFO.ID; switch (id) { case "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}": name = "firefox"; break; case "{a463f10c-3994-11da-9945-000d60ca027b}": name = "flock"; break; } } catch (e) { } return name; }, getMostRecentWindow: function(type) { var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] .getService(Components.interfaces.nsIWindowMediator); return wm.getMostRecentWindow(type); }, extensionPath: function(appid) { return Components.classes["@mozilla.org/extensions/manager;1"].getService( Components.interfaces.nsIExtensionManager).getInstallLocation(appid) .getItemLocation(appid); }, extensionVersion: function(id) { var ver = null; try { var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"] .getService(Components.interfaces.nsIRDFService); var managerSource = Components.classes["@mozilla.org/extensions/manager;1"] .getService(Components.interfaces.nsIExtensionManager).datasource; var extension = rdf.GetResource("urn:mozilla:item:" + id); var versionResource = rdf .GetResource("http://www.mozilla.org/2004/em-rdf#version"); var versionItem = managerSource.GetTarget(extension, versionResource, true); ver = versionItem.QueryInterface(Components.interfaces.nsIRDFLiteral).Value; } catch (e) { } return ver; }, addListener: function(element, event, f, context, capture) { element.addEventListener(event, Prototype.F.bindAsEventListener(f,context), capture); }, newURI: function(spec,base) { var service = Components.classes["@mozilla.org/network/io-service;1"]. getService(Components.interfaces.nsIIOService); if (base != null) { if (Prototype.O.isString(base)) { base = service.newURI(base,null,null); } } return service.newURI(spec,null,base); }, getURLHost: function(url) { var re = new RegExp( "^(?:[a-zA-Z][a-zA-Z0-9+-.]*://)?(?:[^@/]*@)?([^:@/]*)(?::[0-9]*)?(?:/.*)?$"); var match = re.exec(url); if (match == null) { return null; } return match[1]; }, getSiteName: function(url) { var host = this.getURLHost(url); if (host == undefined) { return undefined; } if (host == null) { return null; } return host.replace(new RegExp("^www\\."), ""); }, getHighLevelDomainName: function(url) { var site = this.getSiteName(url); if (site === null) { return null; } var lastDotIndex = site.lastIndexOf('.'); if (lastDotIndex == -1) { return null; } var tld = site.substring(lastDotIndex + 1).toLowerCase(); if (tld.search(/^\d+$/) != -1) { return null; } var nParts = Utils.HIGH_LEVEL_DOMAIN_PARAMS.domainPartsPerTLD[tld]; if (nParts === undefined) { nParts = Utils.HIGH_LEVEL_DOMAIN_PARAMS.nDomainPartsUnrecognizedTLD; } for ( var nPartsFound = 1; nPartsFound < nParts; ++nPartsFound) { lastDotIndex = site.lastIndexOf(".", lastDotIndex - 1); if (lastDotIndex == -1) { break; } } return site.substring(lastDotIndex + 1); }, getFaviconURLs: function(url,website) { var w = website || Utils.getHighLevelDomainName(url); var index = w.indexOf('/'); if (index != -1) { w = w.substr(0,index); } var res = [ "http://www." + w + "/favicon.ico", "http://" + w + "/favicon.ico"]; // Patch for denver post if (w == "denverpost.com") { res.push("http://extras.mnginteractive.com/live/media/favIcon/dpo/favicon.ico"); } if (!website) { var h = Utils.getURLHost(url); if ((h != w) && (h != "www." + w)) { res.push("http://" + h + "/favicon.ico"); } } return res; }, scaleClipAndCenterImageInBox: function(targetWidth,targetHeight,imgNode,image) { if (imgNode.src != image.src) { imgNode.src = image.src; } var xFactor = targetWidth / image.width; var yFactor = targetHeight / image.height; var factor = Math.max(Math.min(xFactor,yFactor,Utils.IMAGE_SCALING_CONSTS.MAX_THUMBNAIL_SCALING_FACTOR),Utils.IMAGE_SCALING_CONSTS.MIN_THUMBNAIL_SCALING_FACTOR); var width = Math.round(image.width * factor); var height = Math.round(image.height * factor); var t = (targetHeight - height)/2; var l = (targetWidth - width)/2; Prototype.E.setStyle(imgNode,{ width: width + "px", height: height + "px", position: "absolute", top: t + "px", left: l + "px"}); imgNode.width = width; imgNode.height = height; }, toISO8601DateString: function(date) { var du = date.getTime(); du += date.getTimezoneOffset()*60000; var ms = date.getUTCMilliseconds(); return (new Date(du)).toLocaleFormat(Utils.ISO8601_DATE_FORMAT) + "." + ms + "Z"; }, parseISO8601Date: function(dateString) { var match = Utils.ISO8601_DATE_PATTERN.exec(dateString); if (match === null) { return null; } var year = parseInt(match[1], 10); var month = parseInt(match[2], 10) - 1; var day = parseInt(match[3], 10); var hour = parseInt(match[4], 10); var minute = parseInt(match[5], 10); var second = parseInt(match[6], 10); var milli = 0; if (match[7]) { milli = parseInt(match[7], 10); } var tzSign = "+"; var tzHour = 0; var tzMinute = 0; if (match[8] != "Z") { tzSign = match[9]; tzHour = parseInt(match[10], 10); tzMinute = parseInt(match[11], 10); } var d = Date.UTC(year, month, day, hour, minute, second, milli); var offset = (tzHour * 3600 + tzMinute * 60) * 1000; if (tzSign == "-") { offset = -offset; } d -= offset; return new Date(d); }, dateDistanceInWords: function(from_time, to_time, localizedStrings) { var from_s = from_time.getTime() / 1000.0; var to_s = to_time.getTime() / 1000.0; var distance_in_minutes = Math.round(Math.abs(to_s - from_s) / 60); var distance_in_seconds = Math.round(Math.abs(to_s - from_s)); if (distance_in_minutes <= 1) { return localizedStrings.get("general.dates.intervals.less_than_one_minute"); } else if (distance_in_minutes <= 59) { return localizedStrings.get("general.dates.intervals.minutes", [ distance_in_minutes ]); } else if (distance_in_minutes <= 1439) { return localizedStrings.get("general.dates.intervals.hours", [ Math .round(distance_in_minutes / 60.0) ]); } else if (distance_in_minutes <= 43199) { return localizedStrings.get("general.dates.intervals.days", [ Math .round(distance_in_minutes / 1440.0) ]); } else if (distance_in_minutes <= 525599) { return localizedStrings.get("general.dates.intervals.months", [ Math .round(distance_in_minutes / 43200.0) ]); } else { return localizedStrings.get("general.dates.intervals.years", [ Math .round(distance_in_minutes / 525600.0) ]); } }, dateInWords: function(from_time, to_time, localizedStrings) { var from_s = from_time.getTime() / 1000.0; var to_s = to_time.getTime() / 1000.0; var distance_in_minutes = Math.round(Math.abs(to_s - from_s) / 60); var distance_in_seconds = Math.round(Math.abs(to_s - from_s)); if (distance_in_minutes < 1) { return localizedStrings.get("general.dates.intervals.less_than_one_minute_ago"); } else if (distance_in_minutes < 60) { return localizedStrings.get("general.dates.ago", [ localizedStrings.get( "general.dates.intervals.minutes", [ distance_in_minutes ]) ]); } else if (distance_in_minutes < 90) { return localizedStrings.get("general.dates.ago", [ localizedStrings.get( "general.dates.intervals.hour", [ 1 ]) ]); } else if (distance_in_minutes < 1440 / 2) { return localizedStrings.get("general.dates.ago", [ localizedStrings.get( "general.dates.intervals.hours", [ Math .round(distance_in_minutes / 60.0) ]) ]); } else { // Go by day in week var from_day = Math.floor(from_s / (24 * 60 * 60)); var to_day = Math.floor(to_s / (24 * 60 * 60)); // FIXME: deal with sunday/monday week starts var from_sow = from_day - from_time.getDay(); var to_sow = to_day - to_time.getDay(); if (from_day == to_day) { return localizedStrings.get("general.dates.intervals.today"); } else if (to_day - from_day == 1) { return localizedStrings.get("general.dates.intervals.yesterday"); } else if (to_sow - from_sow <= 7) { var dow = localizedStrings.get("general.dates.weekday." + from_time.getDay()); if (to_sow > from_sow) { dow = localizedStrings.get("general.dates.last", [ dow ]); } return dow; } else { var from_som = from_day - (from_time.getDate() - 1); var to_som = to_day - (to_time.getDate() - 1); // Go by weeks if ((to_sow - from_sow <= 21) || (from_som == to_som)) { return localizedStrings.get("general.dates.ago", [ localizedStrings .get("general.dates.intervals.weeks", [ Math .round((to_sow - from_sow) / 7) ]) ]); } else { // Go by months if (to_som - from_som < 45) { return localizedStrings.get("general.dates.intervals.last_month"); } else { var mname = localizedStrings.get("general.dates.month." + from_time.getMonth()); if (from_time.getFullYear() != to_time.getFullYear()) { mname = localizedStrings.get("general.dates.month_with_year", [ mname, from_time.getFullYear() ]); } return mname; } } } } }, toXml: function(parent,object) { var ret = parent; if (typeof(parent) == "string") { var d = document.implementation.createDocument("","",null); parent = d.createElement(parent); d.appendChild(parent); ret = d; } var doc = (parent.nodeType == Components.interfaces.nsIDOMNode.DOCUMENT_NODE) ? parent : parent.ownerDocument; var type = typeof object; switch (type) { case 'undefined': case 'function': case 'unknown': return; case 'number': case 'string': case 'boolean': { var t = doc.createTextNode(object.toString()); parent.appendChild(t); return ret; } } if (object === null) { return ret; } if (Prototype.O.isArray(object)) { var name = object["__itemName"] || "Item"; var l = object.length; for (var i = 0; i < l; ++i) { var itemElem = doc.createElement(name); parent.appendChild(itemElem); Utils.toXml(itemElem,object[i]); } return ret; } if (object instanceof Components.interfaces.nsIDOMNode) { parent.appendChild(doc.importNode(object,true)); return ret; } for (var p in object) { if (object[p] !== null) { if (Prototype.S.startsWith(p,"@")) { parent.setAttribute(p.substring(1),object[p].toString()); } else if (p === "__content") { Utils.toXml(parent,object[p]); } else { var e = doc.createElement(p); parent.appendChild(e); Utils.toXml(e,object[p]); } } } return ret; }, getPixelsFromStyleSizeStr: function(size) { var res = /^([0-9]+(?:\.[0-9]*)?)(?:px)?$/.exec(size); return res === null ? null : parseFloat(res[1]); }, getStyleSize: function(element,property) { var res = Prototype.E.getStyle(element,property); return res === null ? null : this.getPixelsFromStyleSizeStr(res); }, containsAllOf: function(text,searchStrings) { return searchStrings.every(function(searchString) { if (typeof(searchString) == "string") { return (text.indexOf(searchString) != -1); } else { return this.containsAnyOf(text,searchString); } },this); }, containsAnyOf: function(text,searchStrings) { return searchStrings.some(function(searchString) { if (typeof(searchString) == "string") { return (text.indexOf(searchString) != -1); } else { return this.containsAllOf(text,searchString); } },this); }, getClientWidth: function(element) { if (element.clientWidth !== undefined) { return element.clientWidth; } if (element.boxObject !== undefined) { return element.boxObject.width - ( this.getStyleSize(element,"padding-left") + this.getStyleSize(element,"padding-right") + this.getStyleSize(element,"border-left") + this.getStyleSize(element,"border-right") ); } return null; }, getClientHeight: function(element) { if (element.clientHeight !== undefined) { return element.clientHeight; } if (element.boxObject !== undefined) { return element.boxObject.height - ( this.getStyleSize(element,"padding-top") + this.getStyleSize(element,"padding-bottom") + this.getStyleSize(element,"border-top") + this.getStyleSize(element,"border-bottom") ); } return null; }, truncateNodeTextToMaxDimensions: function(truncNode, text, guessChars, maxHeight, maxWidth) { if (!maxWidth && !maxHeight) { throw "Must provide at least one of maximum width or maximum height"; } text = Prototype.S.strip(text); var nChars = text.length; var minChars = 0; var maxChars = nChars; var curChars = (guessChars < 0) ? nChars : Math.max(nChars,Math.min(1,guessChars)); truncNode.textContent = text.substr(0,curChars)+((curChars < nChars) ? "..." : ""); var curh; var curw; var curv; var maxv = maxHeight ? (maxWidth ? maxHeight * maxWidth : maxHeight) : maxWidth; while (maxChars > minChars) { curv = 1; if (maxHeight) { curv = this.getClientHeight(truncNode); } if (maxWidth) { curv = curv * this.getClientWidth(truncNode); } if ((maxHeight && this.getClientHeight(truncNode) > maxHeight) || (maxWidth && this.getClientWidth(truncNode) > maxWidth)) { // If we have too much text, decrease the max limit maxChars = curChars - 1; } else { // If we haven't hit the limit, increase the min limit minChars = curChars; } if (minChars >= maxChars) { curChars = maxChars; break; } // Try to guess the next best number of chars to use based on values var minNext = Math.max(minChars,Math.floor(maxChars/3 + minChars*2/3)); if (minNext == curChars) { ++minNext; } var maxNext = Math.min(maxChars,Math.ceil(maxChars*2/3 + minChars/3)); if (maxNext == curChars) { --maxNext; } // Try to guess a value for the next number of chars to try based on // dimensions // and trim to reasonable bounds curChars = Math.min(maxNext,Math.max(minNext,Math.round(curChars * maxv / curv))); truncNode.textContent = text.substr(0,curChars)+((curChars < nChars) ? "..." : ""); } var t = text.substr(0,curChars)+((curChars < nChars) ? "..." : ""); truncNode.textContent = t; return t; }, Twitter: { getUserURL: function(userName) { return "http://twitter.com/" + encodeURIComponent(userName); } }, md5: function(str) { var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]. createInstance(Components.interfaces.nsIScriptableUnicodeConverter); // we use UTF-8 here, you can choose other encodings. converter.charset = "UTF-8"; // result is an out parameter, // result.value will contain the array length var result = {}; // data is an array of bytes var data = converter.convertToByteArray(str, result); var ch = Components.classes["@mozilla.org/security/hash;1"] .createInstance(Components.interfaces.nsICryptoHash); ch.init(ch.MD5); ch.update(data, data.length); var hash = ch.finish(false); return this.toHexString(hash); }, toHexString: function(bytes) { var res = []; var l = bytes.length; for (var i = 0; i < bytes.length; ++i) { res.push(Prototype.N.toPaddedString(bytes.charCodeAt(i),2,16)); } return res.join(''); }, getAncestorOrSelfAttributeOrProperty: function(elem,name) { var val = elem.getAttribute(name); if (val) { return val; } for (var p = elem.parentNode; p; p = p.parentNode) { if (p[name]) { return p[name]; } else if (p.getAttribute && p.getAttribute(name)) { return p.getAttribute(name); } } return null; }, getAncestorOrSelfAggregateAttributeOrProperty: function(elem,name) { var val = elem.getAttribute(name); var cur = elem; while (!val || Prototype.S.startsWith(val,'$')) { // We find the next value up the parent chain var next = null; for (var p = cur.parentNode; p; p = p.parentNode) { if (p[name]) { next = p[name]; break; } else if (p.getAttribute && p.getAttribute(name)) { next = p.getAttribute(name); break; } } // If none was found, there is no value // (note, even if the value starts with $, // we consider it nonexistent if there is no matching parent // value if (!next) { return null; } // If the current value is empty, we simply // take the parent. Otherwise, we replace the initial $ with // the parent. Note that it may still begin with $, in which // case the loop will continue if (!val) { val = next; } else { val = next + val.substring(1); } } return val; }, isPrivateBrowsingEnabled: function() { var pbs = null; try { pbs = Components.classes["@mozilla.org/privatebrowsing;1"] .getService(Components.interfaces.nsIPrivateBrowsingService); } catch (ex) { return false; } if (!pbs) { return false; } return pbs.privateBrowsingEnabled; }, }; Utils.LocalizedBundle = Prototype.Class.create({ initialize: function(doc) { this.bundle = doc.getElementById("glydo-stringbundle"); this.defaultBundle = doc.getElementById("glydo-default-stringbundle"); }, get: function(key, args) { var str = null; try { if (args === undefined) { try { str = this.bundle.getString(key); } catch (e) { str = this.defaultBundle.getString(key); } } else { try { str = this.bundle.getFormattedString(key, args); } catch (e) { str = this.defaultBundle.getFormattedString(key, args); } } } catch (e) { return null; } return str; }, }); Utils.ISO8601_DATE_FORMAT = "%Y-%m-%dT%H:%M:%S"; Utils.ISO8601_DATE_PATTERN = /^(\d{4})-?(\d{2})-?(\d{2})T(\d{2}):?(\d{2}):?(\d{2})(?:\.(\d{3}))?(Z|([+-])(\d{2}):?(\d{2}))?$/; Utils.IMAGE_SCALING_CONSTS = { MAX_THUMBNAIL_SCALING_FACTOR: 1.25, MIN_THUMBNAIL_SCALING_FACTOR: 0.1, }; Utils.APP_INFO = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULAppInfo); Utils.HIGH_LEVEL_DOMAIN_PARAMS = { domainPartsPerTLD: { "aero" :2, "asia" :2, "biz" :2, "cat" :2, "com" :2, "coop" :2, "edu" :2, "gov" :2, "info" :2, "int" :2, "jobs" :2, "mil" :2, "mobi" :2, "museum" :2, "name" :2, "net" :2, "org" :2, "pro" :2, "tel" :2, "travel" :2, "post" :2, "geo" :2, "cym" :2, "fm": 2, "am": 2, "tv": 2, "cd": 2, "dj": 2, "mu": 2 }, nDomainPartsUnrecognizedTLD: 3 };